{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import torch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tensor and tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.0000e+00,  0.0000e+00,  1.7264e-42],\n",
      "        [ 0.0000e+00,  7.0065e-45,  0.0000e+00],\n",
      "        [-6.9059e+06,  6.5160e-43,  0.0000e+00],\n",
      "        [ 0.0000e+00,  9.1843e-41,  0.0000e+00],\n",
      "        [-5.5417e+07,  6.5160e-43,  0.0000e+00]])\n",
      "torch.Size([5, 3])\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "x = torch.Tensor(5, 3) # （接近于全0的矩阵）\n",
    "# 构造一个未初始化的5*3的矩阵\n",
    "print(x)\n",
    "print(x.size())\n",
    "print(x.requires_grad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Tensor只能定义张量，不可设置自动求导\n",
    "x = torch.Tensor(5, 3, requires_grad=True)\n",
    "print(x.requires_grad)\n",
    "'''\n",
    "an invalid combination of arguments\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(5)\n",
      "torch.Size([])\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "x = torch.tensor(5,)\n",
    "print(x)\n",
    "print(x.size())\n",
    "print(x.requires_grad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([  5,  10])\n",
      "torch.Size([2])\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "x = torch.tensor([5, 10], requires_grad=True)\n",
    "print(x)\n",
    "print(x.size())\n",
    "print(x.requires_grad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.1195,  0.0569,  0.8007],\n",
      "        [ 0.9525,  0.2327,  0.2942],\n",
      "        [ 0.4098,  0.7869,  0.9723],\n",
      "        [ 0.2134,  0.1945,  0.2924],\n",
      "        [ 0.3625,  0.5926,  0.0879]])\n",
      "torch.Size([5, 3])\n",
      "tensor([ 0.0569,  0.2327,  0.7869,  0.1945,  0.5926])\n"
     ]
    }
   ],
   "source": [
    "x = torch.rand(5, 3)# 构造一个随机初始化的矩阵\n",
    "print(x)\n",
    "print(x.size())\n",
    "print(x[:,1]) # 输出x的第二列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([ 2.,  3.,  4.,  5.])\n",
      "torch.Size([4])\n",
      "tensor(5.)\n",
      "5.0\n"
     ]
    }
   ],
   "source": [
    "# tensor 即为高级的array\n",
    "x = torch.arange(2, 6)\n",
    "print(x)\n",
    "print(x.size())\n",
    "print(x[3])\n",
    "print(x[3].item())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(14.)\n"
     ]
    }
   ],
   "source": [
    "_sum = x.sum()\n",
    "print(_sum)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 1.0867,  1.8500,  0.4626],\n",
      "        [ 1.3851,  1.3445,  0.7102],\n",
      "        [ 0.2457,  0.6875,  1.3917],\n",
      "        [ 0.8695,  1.0540,  0.8676],\n",
      "        [ 0.4176,  0.8568,  0.8107]])\n",
      "tensor([[ 1.0867,  1.8500,  0.4626],\n",
      "        [ 1.3851,  1.3445,  0.7102],\n",
      "        [ 0.2457,  0.6875,  1.3917],\n",
      "        [ 0.8695,  1.0540,  0.8676],\n",
      "        [ 0.4176,  0.8568,  0.8107]])\n",
      "tensor([[ 1.0867,  1.8500,  0.4626],\n",
      "        [ 1.3851,  1.3445,  0.7102],\n",
      "        [ 0.2457,  0.6875,  1.3917],\n",
      "        [ 0.8695,  1.0540,  0.8676],\n",
      "        [ 0.4176,  0.8568,  0.8107]])\n"
     ]
    }
   ],
   "source": [
    "'''\n",
    "torch的各种加法实现\n",
    "a + b\n",
    "torch.add(a, b, out=c)\n",
    "a.add_(b)\n",
    "'''\n",
    "x = torch.rand(5, 3)\n",
    "y = torch.rand(5, 3)\n",
    "print(x + y)\n",
    "print(torch.add(x, y))\n",
    "print(y.add_(x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 1.3911,  2.8488,  0.6519],\n",
      "        [ 2.1949,  2.2916,  1.3786],\n",
      "        [ 0.3310,  1.1756,  1.7986],\n",
      "        [ 1.5336,  1.5587,  0.9883],\n",
      "        [ 0.4456,  1.6811,  1.4553]])\n"
     ]
    }
   ],
   "source": [
    "result = torch.Tensor(5, 3)\n",
    "torch.add(x, y, out=result)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## numpy桥"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### tensor到numpy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([ 1.,  1.,  1.,  1.,  1.])\n",
      "[1. 1. 1. 1. 1.]\n"
     ]
    }
   ],
   "source": [
    "a = torch.ones(5)\n",
    "b = a.numpy() \n",
    "print(a)\n",
    "print(b) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### torch的tensor numpy的array共享存储空间"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([ 2.,  2.,  2.,  2.,  2.])\n",
      "[2. 2. 2. 2. 2.]\n"
     ]
    }
   ],
   "source": [
    "a.add_(1)\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.FloatTensor <class 'torch.Tensor'>\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "print(a.type(), type(a))\n",
    "# torch.FloatTensor ：数据类型\n",
    "# <class 'torch.Tensor'> ： 类别\n",
    "print(isinstance(a, torch.FloatTensor))\n",
    "# a是一个类，type()是类中定义的一个函数，返回具体的数据类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'>\n"
     ]
    }
   ],
   "source": [
    "# 'numpy.ndarray' object has no attribute 'type'\n",
    "print(type(b))\n",
    "# <class 'numpy.ndarray'>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.DoubleTensor <class 'torch.Tensor'>\n"
     ]
    }
   ],
   "source": [
    "x = torch.DoubleTensor([1, 1, 1])\n",
    "print(x.type(), type(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### numpy到torch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1. 1. 1. 1. 1.]\n",
      "tensor([ 1.,  1.,  1.,  1.,  1.], dtype=torch.float64)\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "a = np.ones(5)\n",
    "b = torch.from_numpy(a)\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2. 2. 2. 2. 2.]\n",
      "tensor([ 2.,  2.,  2.,  2.,  2.], dtype=torch.float64)\n"
     ]
    }
   ],
   "source": [
    "np.add(a, 1, out=a)\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Variable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 1.,  1.],\n",
      "        [ 1.,  1.]]) torch.FloatTensor <class 'torch.Tensor'>\n",
      "tensor([[ 3.,  3.],\n",
      "        [ 3.,  3.]]) torch.FloatTensor <class 'torch.Tensor'>\n",
      "tensor([[ 27.,  27.],\n",
      "        [ 27.,  27.]]) torch.FloatTensor <class 'torch.Tensor'>\n",
      "tensor(27.)\n"
     ]
    }
   ],
   "source": [
    "from torch.autograd import Variable\n",
    "x = Variable(torch.ones(2, 2), requires_grad=True)\n",
    "print(x, x.type(), type(x))\n",
    "y = x + 2\n",
    "print(y, y.type(), type(y))\n",
    "z = y * y * 3\n",
    "print(z, z.type(), type(z))\n",
    "out = z.mean()\n",
    "print(out)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 4.5000,  4.5000],\n",
      "        [ 4.5000,  4.5000]])\n"
     ]
    }
   ],
   "source": [
    "out.backward()\n",
    "# out.backward(torch.Tensor([1.0])) 未设置反向，不能回传\n",
    "print(x.grad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.1745,  1.4591,  0.2354],\n",
      "        [-2.9184,  1.1998,  1.7592],\n",
      "        [-0.1675, -2.2928, -0.4010]]) torch.Size([3, 3])\n",
      "tensor([[ 0.2222,  0.2222,  0.2222],\n",
      "        [ 0.2222,  0.2222,  0.2222],\n",
      "        [ 0.2222,  0.2222,  0.2222]])\n"
     ]
    }
   ],
   "source": [
    "x = Variable(torch.randn(3,3), requires_grad=True)\n",
    "y = x * 2\n",
    "# y = y * 2\n",
    "print(y, y.size())\n",
    "# y.backward() 回传的时候，最终值要是一个标量\n",
    "z = y.mean()\n",
    "z.backward()\n",
    "print(x.grad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([ 0.1205, -0.6340,  0.2931]) torch.Size([3])\n",
      "tensor([ 0.2409, -1.2680,  0.5862]) torch.Size([3])\n",
      "tensor([ 2.,  2.,  2.])\n"
     ]
    }
   ],
   "source": [
    "x = torch.randn(3)\n",
    "print(x, x.size())\n",
    "x = Variable(x, requires_grad=True)\n",
    "y = x * 2\n",
    "print(y, y.size())\n",
    "# grad = [1,1,1]  #gradients can be either Tensors or None, but got int\n",
    "grad = torch.FloatTensor([1, 1, 1]) # 设置反向的梯度\n",
    "y.backward(grad)\n",
    "print(x.grad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([ 1.5724,  0.3190,  0.4156]) torch.Size([3])\n",
      "tensor([    0.1024,   102.4000,  1024.0000])\n"
     ]
    }
   ],
   "source": [
    "x = torch.randn(3)\n",
    "print(x, x.size())\n",
    "x = Variable(x, requires_grad=True)\n",
    "y = x * 2\n",
    "while y.data.norm() < 1000:\n",
    "    y = y * 2\n",
    "gradients = torch.FloatTensor([0.0001,0.1,1.0])\n",
    "y.backward(gradients)\n",
    "print(x.grad)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
